package com.erbao.io.netty.refactor.transport;

import com.erbao.IoUtil;
import com.erbao.io.netty.refactor.rpc.Dispatcher;
import com.erbao.io.netty.refactor.rpc.protocol.MyContent;
import com.erbao.io.netty.refactor.rpc.protocol.MyHeader;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

public class ServerRequestHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof MyPkgMsg) {
            System.out.println("读取到msg："+msg);
            MyPkgMsg requestMsg = (MyPkgMsg) msg;

            String ioThreadName = Thread.currentThread().getName();
            /*io线程和业务线程
            * 1.直接在当前线程处理io和业务
            * 2.使用netty自己的eventloop来处理业务及返回
            * 3.也可以使用自己的线程池。*/

            // 把现有的任务使用已有的线程进行执行。因为一台机器的cpu有限，能开启的线程数也是有限的。
            // ctx.executor().execute(()->{// io线程和业务线程是一个。因为一个线程处理一个连接的所有事件,一个线程一个eventloop，不用加锁.一个selector绑定一个线程处理一个连接线性读写
            ctx.executor().parent().next().execute(()->{// executor eventloop,parent eventloopgroup。从group中挑选下一个线程执行
                String execTreadName = Thread.currentThread().getName();

                // 查看io线程和业务线程是否一样。执行的参数和调用的参数，要看是不是一个参数，判断通信有没有错位
                String responseStr = "IO线程：".concat(ioThreadName).concat(" 执行线程：").concat(execTreadName).concat(" server接收参数：").concat(Objects.toString(requestMsg.getContent().getArgs()[0], ""));
                System.out.println(responseStr);

                MyContent requestContent = requestMsg.getContent();
                Object result = Dispatcher.dispatcher.getResult(requestContent);

                MyContent content = new MyContent();
                content.setResponseObj(result);
                byte[] bodyBytes = IoUtil.serialize(content);

                MyHeader header = new MyHeader();
                header.setRequestId(requestMsg.getHeader().getRequestId());
                header.setFlag(0x14141424);
                header.setContentLength(bodyBytes.length);
                byte[] headerBytes = IoUtil.serialize(header);
                System.out.println("header length:"+headerBytes.length+"body length:"+bodyBytes.length);

                ByteBuf responseByteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(headerBytes.length + bodyBytes.length);
                responseByteBuf.writeBytes(headerBytes);
                responseByteBuf.writeBytes(bodyBytes);

                ctx.writeAndFlush(responseByteBuf);
            });


        }


    }
}